﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Http;
using TccServicos.Models;
using TccServicos.Negocio;
using TccServicos.Util;

namespace TccServicos.Controllers
{
    public class AnimalController : ApiController
    {
        #region Atributos
        private string sThread = "";
        #endregion

        #region WebApis do TCC Animal
        [HttpPost]
        public RetornoServico SaveAnimal(Animal objeto)
        {
            sThread = Util.Util.NextHex(4);
            string nomeFuncao = string.Format("{0} [{1}]", "SaveAnimal", sThread);

            try
            {
                if (!Validacao.ObjetoValido(objeto))
                {
                    Log.GravarLog(string.Format("{0}: {1}", nomeFuncao, Validacao.objetoInvalido));
                }

                string jsonEntrada = JsonConvert.SerializeObject(objeto, new JsonSerializerSettings()
                {
                    NullValueHandling = NullValueHandling.Ignore
                });

                Log.GravarLog(string.Format("{0}: {1}", nomeFuncao, jsonEntrada));

                using (adoteEntities contexto = new adoteEntities())
                {
                    if (objeto.animalTipo.Equals(AnimalTipo.Doacao))
                    {
                        var objetoSalvar = new CADASTRO_ANIMAL
                        {
                            ID_CADASTRO_ANIMAL = objeto.id,
                            ID_CADASTRO_PESSOA = objeto.pessoa.idPessoa,
                            DATA = DateTime.Now,
                            ID_GENERO = (Validacao.ObjetoValido(objeto.genero) ? objeto.genero.idGenero : (int?)null),
                            ID_FOTO = (Validacao.ObjetoValido(objeto.foto) ? objeto.foto.idFoto : (int?)null),
                            ID_RACA = (Validacao.ObjetoValido(objeto.raca) ? objeto.raca.idRaca : (int?)null),
                            IDADE = objeto.idade,
                            ID_PORTE = (Validacao.ObjetoValido(objeto.porte) ? objeto.porte.idPorte : (int?)null),
                            PESO = objeto.peso,
                            ID_UF = (Validacao.ObjetoValido(objeto.cidade) && Validacao.ObjetoValido(objeto.cidade.uf) ? objeto.cidade.uf.idUf : (int?)null),
                            ID_CIDADE = (Validacao.ObjetoValido(objeto.cidade) ? objeto.cidade.idCidade : (int?)null),
                            TELEFONE = objeto.telefone,
                            EMAIL = objeto.email,
                            DESCRICAO = objeto.descricao,
                            VACINAS = objeto.vacinas,
                            NOME = objeto.nome,
                        };
                        if (objeto.excluir)
                        {
                            var idFotoDeletar = this.BuscaIdFoto(objetoSalvar.ID_CADASTRO_ANIMAL);
                            
                            contexto.CADASTRO_ANIMAL.Attach(objetoSalvar);
                            contexto.Entry(objetoSalvar).State = System.Data.EntityState.Deleted;
                            contexto.SaveChanges();

                            if (idFotoDeletar.HasValue && idFotoDeletar.Value > 0)
                                this.DeleteFoto(idFotoDeletar.Value);
                        }
                        else if (objeto.id > 0)
                        {
                            var idFotoDeletar = this.BuscaIdFoto(objetoSalvar.ID_CADASTRO_ANIMAL);
                            
                            contexto.CADASTRO_ANIMAL.Attach(objetoSalvar);
                            contexto.Entry(objetoSalvar).State = System.Data.EntityState.Modified;
                            contexto.SaveChanges();

                            if (idFotoDeletar.HasValue && idFotoDeletar.Value > 0)
                                this.DeleteFoto(idFotoDeletar.Value);
                        }
                        else
                        {
                            contexto.CADASTRO_ANIMAL.Add(objetoSalvar);
                            contexto.SaveChanges();
                        }

                        /*
                        if (!string.IsNullOrEmpty(objeto.email) && !objeto.excluir)
                            System.Threading.Tasks.Task.Run(() => 
                                TccServicos.Servicos.Servicos.EnviaEmail(objeto.email, 
                                "Busca Pet - Cadastro", "Obrigado por cadastrar " + objeto.nome + ".", 
                                "Esperamos que você encontre um novo lar para seu animal de estimação."));
                        */
                        if (!string.IsNullOrEmpty(objeto.email) && !objeto.excluir)
                        {
                            string endereco = Util.Util.BuscaConfig("EnderecoWebApi");

                            EmailPayload emailPayload = new EmailPayload()
                            {
                                para = objeto.email,
                                titulo = "Busca Pet - Cadastro",
                                mensagem1 = "Obrigado por cadastrar " + objeto.nome + ".",
                                mensagem2 = "Esperamos que você encontre um novo lar para seu animal de estimação.",
                            };
                            string json = JsonConvert.SerializeObject(emailPayload, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });

                            WebClient webClient = new WebClient();
                            webClient.Encoding = new System.Text.UTF8Encoding();
                            webClient.Headers[HttpRequestHeader.ContentType] = "application/json; charset=utf-8";
                            webClient.UploadStringAsync(new Uri(endereco + "api/Email/EnviaEmail"), json);

                            /*
                            NotificacaoPayload notificacaoPayload = new NotificacaoPayload()
                            {
                                token = "6db992177e09945a004f9ef57a660e546fb2e37b1cd3d670769591af2ef2cef3",
                                mensagem = "Um novo animal foi cadastrado no app, entre e confira",
                            };
                            string jsonNotificacao = JsonConvert.SerializeObject(notificacaoPayload, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });

                            WebClient webClientNot = new WebClient();
                            webClientNot.Encoding = new System.Text.UTF8Encoding();
                            webClientNot.Headers[HttpRequestHeader.ContentType] = "application/json; charset=utf-8";
                            webClientNot.UploadStringAsync(new Uri(endereco + "api/Notificacao/EnviaNotificacao"), jsonNotificacao);
                            */

                            NotificacaoPayload notificacaoPayload = new NotificacaoPayload()
                            {
                                token = "", //Enviar para todos
                                mensagem = "Um novo animal foi cadastrado, entre no app e confira",
                            };
                            string jsonNotificacao = JsonConvert.SerializeObject(notificacaoPayload, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });

                            WebClient webClientNot = new WebClient();
                            webClientNot.Encoding = new System.Text.UTF8Encoding();
                            webClientNot.Headers[HttpRequestHeader.ContentType] = "application/json; charset=utf-8";
                            webClientNot.UploadStringAsync(new Uri(endereco + "api/PessoaNotificacao/EnviaNotificacao"), jsonNotificacao);
                        }

                        Log.GravarLog(string.Format("{0}: {1}", nomeFuncao, Validacao.salvoComSucesso));
                        return Util.Util.RetornoOk(objetoSalvar.ID_CADASTRO_ANIMAL);
                    }
                    else if (objeto.animalTipo.Equals(AnimalTipo.Abandonado))
                    {
                        var objetoSalvar = new CADASTRO_ANIMAL_ABANDONADO
                        {
                            ID_CADASTRO_ABANDONADO = objeto.id,
                            ID_CADASTRO_PESSOA = objeto.pessoa.idPessoa,
                            DATA = DateTime.Now,
                            DESCRICAO = objeto.descricao,
                            LATITUDE = objeto.latitude,
                            LONGITUDE = objeto.longitude,
                            LOCALIZACAO = objeto.localizacao,
                            ENDERECO = objeto.endereco,
                            FOTO = objeto.fotoString,
                        };
                        if (objeto.excluir)
                        {
                            contexto.CADASTRO_ANIMAL_ABANDONADO.Attach(objetoSalvar);
                            contexto.Entry(objetoSalvar).State = System.Data.EntityState.Deleted;
                            contexto.SaveChanges();
                        }
                        else if (objeto.id > 0)
                        {
                            contexto.CADASTRO_ANIMAL_ABANDONADO.Attach(objetoSalvar);
                            contexto.Entry(objetoSalvar).State = System.Data.EntityState.Modified;
                            contexto.SaveChanges();
                        }
                        else
                        {
                            contexto.CADASTRO_ANIMAL_ABANDONADO.Add(objetoSalvar);
                            contexto.SaveChanges();
                        }

                        /*
                        if (!string.IsNullOrEmpty(objeto.pessoa.email) && !objeto.excluir)
                            System.Threading.Tasks.Task.Run(() =>
                                TccServicos.Servicos.Servicos.EnviaEmail(objeto.pessoa.email,
                                "Busca Pet - Cadastro", "Obrigado por cadastrar este animal abandonado.",
                                "Esperamos que ele encontre um novo lar."));
                        */
                        if (!string.IsNullOrEmpty(objeto.pessoa.email) && !objeto.excluir)
                        {
                            string endereco = Util.Util.BuscaConfig("EnderecoWebApi");

                            EmailPayload emailPayload = new EmailPayload()
                            {
                                para = objeto.pessoa.email,
                                titulo = "Busca Pet - Cadastro",
                                mensagem1 = "Obrigado por cadastrar este animal abandonado.",
                                mensagem2 = "Esperamos que ele encontre um novo lar.",
                            };
                            string json = JsonConvert.SerializeObject(emailPayload, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });

                            WebClient webClient = new WebClient();
                            webClient.Encoding = new System.Text.UTF8Encoding();
                            webClient.Headers[HttpRequestHeader.ContentType] = "application/json; charset=utf-8";
                            webClient.UploadStringAsync(new Uri(endereco + "api/Email/EnviaEmail"), json);


                            NotificacaoPayload notificacaoPayload = new NotificacaoPayload()
                            {
                                token = "", //Enviar para todos
                                mensagem = "Um animal abandonado foi identificado, entre no app e confira",
                            };
                            string jsonNotificacao = JsonConvert.SerializeObject(notificacaoPayload, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });

                            WebClient webClientNot = new WebClient();
                            webClientNot.Encoding = new System.Text.UTF8Encoding();
                            webClientNot.Headers[HttpRequestHeader.ContentType] = "application/json; charset=utf-8";
                            webClientNot.UploadStringAsync(new Uri(endereco + "api/PessoaNotificacao/EnviaNotificacao"), jsonNotificacao);
                        }

                        Log.GravarLog(string.Format("{0}: {1}", nomeFuncao, Validacao.salvoComSucesso));
                        return Util.Util.RetornoOk(objetoSalvar.ID_CADASTRO_ABANDONADO);
                    }
                    Log.GravarLog(string.Format("{0}: {1}", nomeFuncao, Validacao.salvoComSucesso));
                    return Util.Util.RetornoOk();
                }
            }
            catch (Exception ex)
            {
                Log.GravarLog(string.Format("{0} Erro: {1}", nomeFuncao, ex.ToString()));
                return Util.Util.RetornoErro(ex.ToString());
            }
        }

        private int? BuscaIdFoto(int idCadastroAnimal)
        {
            int? retorno = null;
            using (adoteEntities edm = new adoteEntities())
            {
                retorno = (from t in edm.CADASTRO_ANIMAL.AsNoTracking()
                           where t.ID_CADASTRO_ANIMAL == idCadastroAnimal
                           select t.ID_FOTO).FirstOrDefault();
            }
            return retorno;
        }

        private void DeleteFoto(int idFoto)
        {
            using (adoteEntities contexto = new adoteEntities())
            {
                var objeto = new CADASTRO_FOTO()
                    {
                        ID_FOTO = idFoto,
                    };
                contexto.CADASTRO_FOTO.Attach(objeto);
                contexto.Entry(objeto).State = System.Data.EntityState.Deleted;
                contexto.SaveChanges();
            }
        }

        [HttpGet]
        public RetornoAnimal GetAnimal([FromUri] int? idTipo = null, [FromUri] int? idAnimal = null, [FromUri] int? pagina = null, 
            [FromUri] int? itens = null, [FromUri] int? idCadastro = null,
            [FromUri] int? tipoAnimal = null, [FromUri] int? idGenero = null, [FromUri] int? idRaca = null,
            [FromUri] int? idPorte = null, [FromUri] int? idUf = null, [FromUri] int? idCidade = null,
            [FromUri] int? idadeMin = null, [FromUri] int? idadeMax = null,
            [FromUri] decimal? pesoMin = null, [FromUri] decimal? pesoMax = null)
        {
            sThread = Util.Util.NextHex(4);
            string nomeFuncao = string.Format("{0} [{1}]", "GetAnimal", sThread);

            try
            {
                return new AnimalNegocio(sThread).GetAnimal(idTipo, idAnimal, pagina, itens, idCadastro, tipoAnimal, idGenero,
                    idRaca, idPorte, idUf, idCidade, idadeMin, idadeMax, pesoMin, pesoMax);

                Log.GravarLog(string.Format("{0}: id={1}", nomeFuncao, idAnimal.HasValue ? idAnimal.Value.ToString() : "0"));

                using (adoteEntities contexto = new adoteEntities())
                {
                    int abandonado = AnimalTipo.Abandonado.GetHashCode();
                    int doacao = AnimalTipo.Doacao.GetHashCode();

                    var consulta1 = (from t in contexto.CADASTRO_ANIMAL_ABANDONADO.AsNoTracking()
                                     join p in contexto.CADASTRO_PESSOA.AsNoTracking() on t.ID_CADASTRO_PESSOA equals p.ID_CADASTRO_PESSOA
                                     select new Animal
                                     {
                                         id = t.ID_CADASTRO_ABANDONADO,
                                         animalTipoInt = abandonado,
                                         pessoa = new Pessoa()
                                         {
                                             idPessoa = p.ID_CADASTRO_PESSOA,
                                             nome = p.NOME,
                                         },
                                         data = t.DATA.Value,
                                         descricao = t.DESCRICAO,
                                         latitude = t.LATITUDE,
                                         longitude = t.LONGITUDE,
                                         localizacao = t.LOCALIZACAO,
                                     }).ToList();
                    var consulta2 = (from t in contexto.CADASTRO_ANIMAL.AsNoTracking()
                                     join p in contexto.CADASTRO_PESSOA.AsNoTracking() on t.ID_CADASTRO_PESSOA equals p.ID_CADASTRO_PESSOA
                                     join g in contexto.CADASTRO_GENERO.AsNoTracking() on t.ID_GENERO equals g.ID_GENERO
                                     into gt from g in gt.DefaultIfEmpty()
                                     join r in contexto.CADASTRO_RACA.AsNoTracking() on t.ID_RACA equals r.ID_RACA
                                     into rt from r in rt.DefaultIfEmpty()
                                     join po in contexto.CADASTRO_PORTE.AsNoTracking() on t.ID_PORTE equals po.ID_PORTE
                                     into pot from po in pot.DefaultIfEmpty()
                                     join uf in contexto.CADASTRO_UF.AsNoTracking() on t.ID_UF equals uf.ID_UF
                                     into uft from uf in uft.DefaultIfEmpty()
                                     join c in contexto.CADASTRO_CIDADE.AsNoTracking() on t.ID_CIDADE equals c.ID_CIDADE
                                     into ct from c in ct.DefaultIfEmpty()
                                     select new Animal
                                     {
                                         id = t.ID_CADASTRO_ANIMAL,
                                         animalTipoInt = doacao,
                                         pessoa = new Pessoa()
                                         {
                                             idPessoa = p.ID_CADASTRO_PESSOA,
                                             nome = p.NOME,
                                         },
                                         data = t.DATA,
                                         genero = new Genero()
                                         {
                                             idGenero = g != null ? g.ID_GENERO : 0,
                                             genero = g!= null ? g.GENERO : null,
                                         },
                                         raca = new Raca()
                                         {
                                             idRaca = r != null ? r.ID_RACA : 0,
                                             raca = r != null ? r.RACA : null,
                                         },
                                         idade = t.IDADE,
                                         porte = new Porte()
                                         {
                                             idPorte = po != null ? po.ID_PORTE : 0,
                                             porte = po != null ? po.PORTE : null,
                                         },
                                         peso = t.PESO,
                                         cidade = new Cidade()
                                         {
                                             idCidade = c!= null ? c.ID_CIDADE : 0,
                                             uf = new Uf() 
                                             { 
                                                 idUf = uf != null ? uf.ID_UF : 0, 
                                                 uf = uf != null ? uf.UF : null 
                                             },
                                             cidade = c!= null ? c.CIDADE : null,
                                         },
                                         telefone = t.TELEFONE,
                                         email = t.EMAIL,
                                         descricao = t.DESCRICAO,
                                         vacinas = t.VACINAS,
                                         nome = t.NOME,
                                     }).ToList();

                    var consulta = consulta1.Union(consulta2).OrderByDescending(x => x.data).ToList();
                    if (idTipo.HasValue)
                        consulta = consulta.Where(x => x.animalTipoInt.Equals(idTipo.Value)).ToList();
                    if (idAnimal.HasValue)
                        consulta = consulta.Where(x => x.id.Equals(idAnimal.Value)).ToList();

                    //filtros
                    if (tipoAnimal.HasValue && tipoAnimal.Value > 0)
                        consulta = consulta.Where(x => x.animalTipoInt == tipoAnimal.Value).ToList();
                    if (idGenero.HasValue && idGenero.Value > 0)
                        consulta = consulta.Where(x => x.genero.idGenero == idGenero.Value).ToList();
                    if (idRaca.HasValue && idRaca.Value > 0)
                        consulta = consulta.Where(x => x.raca.idRaca == idRaca.Value).ToList();
                    if (idPorte.HasValue && idPorte.Value > 0)
                        consulta = consulta.Where(x => x.porte.idPorte == idPorte.Value).ToList();
                    if (idUf.HasValue && idUf.Value > 0)
                        consulta = consulta.Where(x => x.cidade.uf.idUf == idUf.Value).ToList();
                    if (idCidade.HasValue && idCidade.Value > 0)
                        consulta = consulta.Where(x => x.cidade.idCidade == idCidade.Value).ToList();
                    if (idadeMin.HasValue && idadeMin.Value > 0)
                        consulta = consulta.Where(x => x.idade >= idadeMin.Value).ToList();
                    if (idadeMax.HasValue && idadeMax.Value > 0)
                        consulta = consulta.Where(x => x.idade <= idadeMax.Value).ToList();
                    if (pesoMin.HasValue && pesoMin.Value > 0)
                        consulta = consulta.Where(x => x.peso >= pesoMin.Value).ToList();
                    if (pesoMax.HasValue && pesoMax.Value > 0)
                        consulta = consulta.Where(x => x.peso <= pesoMax.Value).ToList();

                    if (pagina.HasValue && itens.HasValue)
                        consulta = consulta.Skip((pagina.Value - 1) * itens.Value).Take(itens.Value).ToList();
                    if (idCadastro.HasValue)
                        consulta = consulta.Where(x => x.pessoa.idPessoa.Equals(idCadastro.Value)).ToList();
                    var retorno = consulta.ToList();

                    foreach (var item in retorno)
                    {
                        item.dataFormatada = item.data.ToString("dd/MM/yy HH:mm");
                    }

                    Log.GravarLog(string.Format("{0}: {1}", nomeFuncao, Validacao.consultaComSucesso));

                    return new RetornoAnimal()
                        {
                            lista = retorno,
                        };
                }
            }
            catch (Exception ex)
            {
                Log.GravarLog(string.Format("{0} Erro: {1}", nomeFuncao, ex.ToString()));
                return default(RetornoAnimal);
            }
        }
        #endregion

    }
}